#!/bin/bash
#======================================
# File name:02sed.sh
# Author:liangliangSu
# Email:sll917@hotmail.com
# Date of writing:2022-10-23 11:35
#======================================
: "
sed是Linux三剑客之一。
       Sed是一种非交互式的流编辑器，可动态编辑文件；流编辑器则会在编辑器处理数据之前基于预先提供的一组 规则来编辑数据流 。
       Sed本身是一个管道命令，可以分析 standard input 的，主要是用来分析关键字的使用、统计等，此外还可 以将数据进行替换、删除、选中、选取特定行等功能

1.sed -[]常用的参数及其作用：
-n ：安静模式。在sed的一般用法中，所有来自文件中的数据都会被列出到屏幕上，如果加上-n，则只有经过sed特殊处理的那行（或操作）才会被列出来。
-e ：直接下命令行模式上进行sed的动作编辑。
-f ：直接将sed的动作写在一个文件内，-f filename 则可以执行file内的sed动作。
-r ：sed的动作支持的是扩展型正则表达式的语法（默认是基础正则表达式的语法）。
-i ：可直接对源文件内容进行修改。。危险操作
-h或–help：显示帮助；
-V或–version：显示版本信息

2.function有下面这些参数
i ：插入，在目标行的上面新增一行。
a ：插入，在目标行的下面新增一行。
d ：删除所选行。
p ：打印，也就是将某个选择的数据打印出来，通常参数-p与参数-n搭配使用。
s ：替换，可以直接进行替换的工作。
c ：替换，c的后面可以接替字符串，这些字符串可以替换n1，n2之间的行。
w ：写并追加模板块到file末尾。
W ： 写并追加模板块的第一行到file末尾。
! ：表示后面的命令对所有没有被选定的行发生作用。
= ：打印当前行号; # 把注释扩展到下一个换行符以前。
以上参数皆不改变原文件内容

3.sed替换标记
g ：表示行内全面替换;
x： 表示互换模板块中的文本和缓冲区中的文本;
y ：表示把一个字符翻译为另外的字符（但是不用于正则表达式）;
\1： 子串匹配标记;
& ：已匹配字符串标记;

4.sed元字符集
^ 匹配行开始，如：/^ sed/匹配所有以sed开头的行
$ 匹配行结束，如：/sed$/匹配所有以sed结尾的行;
.： 匹配一个非换行符的任意字符，如：/s.d/匹配s后接一个任意字符，后是d;
*：匹配0个或多个字符，如：/*sed/匹配所有模板是一个或多个空格后紧跟sed的行;
[] 匹配一个指定范围内的字符，如/[ss]ed/匹配sed和Sed;
[^] 匹配一个不在指定范围内的字符，如：/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头，紧跟ed的行;
\ (…\ ) 匹配子串，保存匹配的字符，如s/(love)able/\1rs，loveable被替换成lovers;
& 保存搜索字符用来替换其他字符，如s/love/&/，love这成love;
< 匹配单词的开始，如:/\
> 匹配单词的结束，如/love>/匹配包含以love结尾的单词的行;
x{m} 重复字符x，m次，如：/0{5}/匹配包含5个0的行;
x{m,} 重复字符x，至少m次，如：/0{5,}/匹配至少有5个0的行; x{m,n} 重复字符x，至少m次，不多于n次，如：/0{5,10}/匹配5~10个0的行;

#5.各参数的使用
#对function参数的使用
#1）打印行 :
#-n 'n1 p’打印第n行，且原文件内容不变；
#-n ‘n1,n2 p’打印n1到n2行，且原文件内容不变
#2）删除行：
#-n ’ n1 d’ 删除第n行，且原文件内容不变；
#-n ‘n1,n2 d’ 删除n1到n2行，且原文件内容不变
#3）插入行：
#‘ni 内容’ 第n行前添加一行内容，且原文件内容不变 ；
#‘na 内容’ 第n行后添加一行内容，且原文件内容不变
#4）替换行：
#‘nc 新内容’ 将第n行替换成新内容，且原文件内容不变
#5）替换字符
#-n ‘s/old/new/p’ :将文件中每行的第一个old字符换成new字符，打印出只发生变化的行，且源文件内容不变。
#-n ‘s/old/new/pg’ :将文件中全部的old字符换成new字符，打印出只发生变化的行，且源文件内容不变
#-n ‘s/old/new/p2g’ :将文件中每行从第2个old字符开始换成new字符，打印出只发生变化的行，且源文件内容不变。

#对sed动作参数的使用
#6）直接对源文件内容进行操作（-i）

#7）不对源文件内容进行操作（-e）

#6.测试
#1）只显示ifconfig中的IP地址
ifconfig | grep 'inet'|grep -v '127.0'|sed 's/netmask.*//'|grep -v 'inet6'| sed 's/.*inet//'|sed 's/^.//'
ifconfig | grep 'inet'|grep -v 'inet6'|grep -v '127.0.0'|awk '{print $2}'
#2）去掉ssh配置文件中的带#行和空行
sed 's/#.*//g' /etc/ssh/sshd_config | sed '/^$/d'
#3）每一行结尾为.的换成!（“ . ” 需要加转义符 ）

#4）在以m开头的行末尾加上3颗星
"

: "
一, sed命令介绍
sed全称是：Stream EDitor（流编辑器）
Linux sed 命令是利用脚本来处理文本文件，sed 可依照脚本的指令来处理、编辑文本文件。Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

二, sed 的运行模式
当处理数据时，Sed 从输入源一次读入一行，并将它保存到所谓的模式空间pattern space中。所有 Sed 的变换都发生在模式空间。变换都是由命令行上或外部 Sed 脚本文件提供的单字母命令来描述的。大多数 Sed 命令都可以由一个地址或一个地址范围作为前导来限制它们的作用范围。

三,  语法
sed [选项] [地址] [命令] file

1）选项描述
 -n, --quiet, --silent    取消自动打印模式空间
 -e 脚本, --expression=脚本   添加“脚本”到程序的运行列表
 -f 脚本文件, --file=脚本文件  添加“脚本文件”到程序的运行列表
 --follow-symlinks    直接修改文件时跟随软链接
 -i[扩展名], --in-place[=扩展名]    直接修改文件(如果指定扩展名就备份文件)
 -l N, --line-length=N   指定“l”命令的换行期望长度
 --posix  关闭所有 GNU 扩展
 -r, --regexp-extended  在脚本中使用扩展正则表达式
 -s, --separate  将输入文件视为各个独立的文件而不是一个长的连续输入
 -u, --unbuffered  从输入文件读取最少的数据，更频繁的刷新输出
 --help     打印帮助并退出
 --version  输出版本信息并退出
 -a ∶新增， a 的后面可以接字串，而这些字串会在新的一行出现(目前的下一行)～
 -c ∶取代， c 的后面可以接字串，这些字串可以取代 n1,n2 之间的行！
 -d ∶删除，因为是删除啊，所以 d 后面通常不接任何咚咚；
 -i ∶插入， i 的后面可以接字串，而这些字串会在新的一行出现(目前的上一行)；
 -p ∶列印，亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作～
 -s ∶取代，可以直接进行取代的工作哩！通常这个 s 的动作可以搭配正规表示法

 2）地址描述
first~step：步长，每step行，从第first开始；
$：匹配最后一行；
/regexp/：正则表达式匹配行；
number：只匹配指定行；
addr1,addr2：开始匹配addr1行开始，直接addr2行结束；
addr1,+N：从addr1行开始，向后的N行；
addr1,~N：从addr1行开始，到N行结束。

3）地址描述
s/regexp/replacement/：替换字符串；
p：打印当前模式空间；
P：打印模式空间的第一行；
d：删除模式空间，开始下一个循环；
D：删除模式空间的第一行，开始下一个循环；
=：打印当前行号；
a：当前行下面追加文本；
i：当前行上面插入文本；
c：所选行替换新文本；
q：立即退出sed脚本；
r：追加文本来自文件；
: label：label为b和t命令；
b label：分支到脚本中带有标签的位置，如果分支不存在则分支到脚本的末尾；
t label：如果s///是一个成功的替换，才跳转到标签；
h H：复制/追加模式空间到保持空间；
g G：复制/追加保持空间到模式空间；
x：交换模式空间和保持空间内容；
y：把一个字符翻译为另外的字符；
l：打印模式空间的行，并显示控制字符$；
n N：读取/追加下一行输入到模式空间；
w filename：写入当前模式空间到文件；
!：取反、否定；
&：引用已匹配字符串。
"

#2.sed的查看功能
#1,查看passwd文件的第5到第8行内容
echo '(1)----------------------完美分割线-------------------------------'
sed -n '5,8 p' /etc/passwd |head 

#2,查看/etc/passwd 文件中以roo开头的行
echo '(2)----------------------完美分割线-------------------------------'
sed -n '/^roo/ p' /etc/passwd |head -5

#3,忽略大小写，对含有root字符的行打印出来
echo '(3)----------------------完美分割线-------------------------------'
sed -n '/root/I p' /etc/passwd |head -5

#3.sed的查找功能
#查找/etc/passwd 文件中有/bin/bash字符串的行
echo '(4)----------------------完美分割线-------------------------------'
sed -n '\%/bin/bash% p' /etc/passwd |head -5

#4.将 /etc/passwd 第 2~5 行删除打印输出
echo '(5)----------------------完美分割线-------------------------------'
sed '2,5 d' /etc/passwd 

#5.以行为单位的新增
#1,在文件/etc/passwd上的第四行后面添加新字符串
echo '(6)----------------------完美分割线-------------------------------'
sed -e 4a\it-test /etc/passwd | head

#,/etc/passwd第1前追加huawei
echo '(7-1)----------------------完美分割线-------------------------------'
sed '1 i\huawei ' /etc/passwd | head 
sed '/^sll/a liang' /etc/passwd
echo '(7-2)----------------------完美分割线-------------------------------'
sed '/^sll/i liang' /etc/passwd

#6.sed替换功能
#1,/etc/passwd第三行替换为redhat
echo '(8)----------------------完美分割线-------------------------------'
sed '3 c\redhat' /etc/passwd |head
echo "hello world" | sed 's/world/[&]/'

#7.sed的查找及替换功能
#将/etc/passwd的5到10的bin字符串查找出来替换为aaaa
echo '(9)----------------------完美分割线-------------------------------'
sed -n '5,10 s/bin/aaaa/ p' /etc/passwd |head

#8.sed对原文件操作
#1,删除原文件第1行
#sed -i '1 d' /etc/passwd
#2,修改原文件之前备份
#sed -i.bak '1 d' /etc/passwd

#9.分别用first~step语法和命令n语法打印奇数行
echo '(10)----------------------完美分割线-------------------------------'
sed -n '1~2p' 02shell三剑客之sed
sed -n 'p;n' 02shell三剑客之sed
#10）分别用first~step语法和命令n语法打印偶数行
echo '(11)----------------------完美分割线-------------------------------'
sed -n '2~2p' 02shell三剑客之sed
sed -n 'n;p' 02shell三剑客之sed
